package Year21_Month10.day1018;

import java.util.Arrays;

public class ArrayList<E>{
    E[] elementData;
    int size;

    private static final int DEFAULT_CAPACITY = 10;

    public ArrayList(int size){
        if(size <= 0){
            size = DEFAULT_CAPACITY;
        }

        elementData = (E[])new Object[size];
    }

    public ArrayList() {

    }
//=============================================================================================================
    //插入问题：

    //先来试试尾插
    public boolean add(E e){//注意这里是boolean值
        add(size(),e);//这里是在size的位置上插入e,需要写一个add( , )和size方法
        return true;
    }
    //这里解决上面的需要重写的两个方法
    public void add(int index,E e){//有两个参数的add方法
        if(index < 0 || index > size){
            throw  new ArrayIndexOutOfBoundsException("你给的下标有问题");
        }
        ensureCapacity(size);//进行扩容
        for(int i = size - 1; i >= index;i--){
            elementData[i + 1] = elementData[i];
        }
        elementData[index] = e;
        size++;//插入完毕之后size++,因为多了一个元素
    }

    public int size(){
        return size;
    }
    //这里解决add( , )这个方法的扩容问题
    public void ensureCapacity(int size){
        int oldCapacity = elementData.length;
        if(size >= oldCapacity) {
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            elementData = Arrays.copyOf(elementData,newCapacity);//把原来数组的内容拷贝一份
        }
    }

//==============================================================================================================
    //删除问题:

    //删除某一个位置上的对象元素
    public E remove(int index){//这里需要返回值的原因是因为他删除之后要返回这个被删除的对象
        checkRange(index);//判断顺序表下标是否越界，等下要重写这个问题
        E ret = elementData[index];
        for(int i = index;i< size;i++){
            elementData[i] = elementData[i + 1];
        }
        size--;//这里注意，写完了之后,size要减减。
        return ret;
    }
    public void checkRange(int index){
        if(index < 0 || index > size){
            throw new ArrayIndexOutOfBoundsException("index下标越界");
        }
    }
    //删除某一个对象
    public boolean remove(E e){
        int key = indexOf(e);//这里重写这个方法，检查一个对象的下标是多少
        if(key == -1){
            return false;
        }
        remove(key);
        return true;
    }
    //从前往后检查某一个对象所在的下标
    public int indexOf(E e){
        for(int i = 0;i < elementData.length - 1;i++){
            if(elementData[i].equals(e)){
                return i;
            }
        }
        return -1;
    }
    //从后往前检查某一个对象所在的下标
    public int lastIndexOf(E e){
        for(int i = elementData.length -1 ;i > 0;i++){
            if(elementData[i].equals(e)){
                return i;
            }
        }
        return -1;
    }

//=============================================================================================================
    //检查问题：检查该数组中是否有对应的元素
    public boolean contains(E e){
        return -1 != indexOf(e);
    }

//===============================================================================================================
    //获取一个子序列
    public ArrayList<E> subList(int from,int to){
        if(from > to){
            throw new ArrayIndexOutOfBoundsException("给的下标有问题");
        }

        int fac = to - from;
        ArrayList<E> list = new ArrayList<>(fac);
        while(from < to){
            list.add(elementData[from]);
            from++;
        }
        return list;
    }

//================================================================================================================
    //得到和设置元素

    //首先是得到元素get
    public E get(int index){
        checkRange(index);
        return elementData[index];
    }

    //接着是设置元素set
    public void set(int index,E e){
        checkRange(index);
        elementData[index] = e;
    }

//=================================================================================================================
    //再接着是清空元素clear
    public void clear(){
        for (int i = 0; i < elementData.length; i++) {
            elementData[i] = null;
        }
        size = 0;//重置size
    }

//================================================================================================================
    //最后是为了方便输出重写toString
    public String toString(){
        String s = "[";
        for (int i = 0; i < elementData.length - 1; i++) {
            s += elementData[i] + ",";
        }
        s += elementData[elementData.length - 1] + "]";
        return s;
    }

//===================================================================================================================
    //这最后一部分就是测试了
    public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<Integer>(5);

        //尾插法没有问题
        list1.add(1);
        list1.add(2);
        list1.add(3);
        list1.add(4);
        list1.add(5);
        System.out.println(list1);
        //特定位置插入也没问题，也会自动扩容
        list1.add(1,1);
        System.out.println(list1);

        //接下来测试设置元素和获得元素--没有问题
        list1.set(3,5);
        System.out.println(list1.get(3));
        System.out.println(list1);

        //接着测试删除元素--米有问题
        list1.remove(1);
        System.out.println(list1);

        //最后再来获取子串 -- 也没问题
        ArrayList<Integer> list2 = list1.subList(0,2);
        System.out.println(list2);
    }
}
